package com.stylefeng.guns.modular.model.controller;


import com.stylefeng.guns.core.base.tips.SuccessTip;
import com.stylefeng.guns.core.wxutils.login.CommondUtil;
import com.stylefeng.guns.core.wxutils.login.Configure;
import com.stylefeng.guns.core.wxutils.pay.Signature;
import com.stylefeng.guns.core.wxutils.pay.Util;
import com.stylefeng.guns.core.wxutils.pay.WxPlaceOrder;
import com.stylefeng.guns.core.wxutils.pay.XMLParser;
import com.stylefeng.guns.modular.model.service.*;
import com.stylefeng.guns.modular.model.utils.StringUtils;
import com.stylefeng.guns.modular.system.model.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @author 杜长青
 * @description 微信支付接口
 * @date 2018/8/1 下午6:20
 **/
@Controller
@RequestMapping("/wxpay")
public class WxPayController {

    private static final String OUT_TREADE_NUM_PREFIX = "RD-bashi-order-";

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IActualRouteService actualRouteService;

    @Autowired
    private IWeixininfoService weixinuserinfoService;

    @Autowired
    private ITicketPriceService ticketPriceService;

    @Autowired
    private ITicketNumService ticketNumService;

    @Autowired
    private  IStaActCentreService staActCentreService;

    @Autowired
    OrderController orderController;

    @Autowired
    IActivityService activityService;

    @Autowired
    IActivityCentreService activityCentreService;

    @Autowired
    ICarFileService carFileService;

    private Lock lock = new ReentrantLock();

    private Lock tickLock = new ReentrantLock();

    /*
     *   新人一元试乘
     *
     */
    @RequestMapping(value ="tryToRideByUsidActid")
    @ResponseBody
    public Object tryToRideByUsidActid(@RequestParam("activityId")Integer activityid){
        Activity activity=activityService.selectById(activityid);
            return  activity;

    }
    /*
     *   新人一元试乘
     *
     */
    @RequestMapping(value ="tryToRide")
    @ResponseBody
    public Object tryToRide(@RequestParam("userId")Integer userId,@RequestParam("activityId")Integer activityid){
        Map<String, Object> returnMap = new ConcurrentHashMap<String, Object>();
        Order order=orderService.selcetByUserid(userId,1);
        ActivityCentre activityCentre=activityCentreService.selectByActityid(activityid,userId);
        if (order==null&&activityCentre==null){
           //当订单为空的话得到优惠券，支付的时候减去这张优惠券的金额
            ActivityCentre activityCentrenew=new ActivityCentre();
            activityCentrenew.setActivityid(activityid);
            activityCentrenew.setWxuserid(userId);
            activityCentrenew.setActivityState(0);//领取了优惠券
            activityCentrenew.setnDate(new Date());
            activityCentrenew.setuDate(new Date());
            activityCentrenew.insert();
            Activity activity=activityService.selectById(activityid);
            List list=new ArrayList();
            returnMap.put("uptime", activity.getUptime());
            returnMap.put("endtime", activity.getEndtime());
            returnMap.put("id", activity.getId());
            returnMap.put("activity", "1"); // 下单失败
            returnMap.put("msg", "你好,你已经成功领取4元优惠卷");
//            list.add(returnMap);
            return  returnMap;

        }else {
            returnMap.put("activity", "-1"); // 下单失败
            returnMap.put("msg", "您好,你已经领取过优惠券");
        }
        return returnMap;
    }
    /*
     * 判断用户是否为新用户
     *
     */
    @Transactional
    public Order activityorder(Integer userId, ActualRoute actualRoute, Integer payNum ,Integer gosite,Integer endsite){
        SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        SimpleDateFormat sdfdate = new SimpleDateFormat("yyyy-MM-dd");
        String startTime = sdfs.format(new Date());
        Date Tickettime = null;
        Date getontime = null;
        SimpleDateFormat sdfst = new SimpleDateFormat("HH:mm");
        StaActCentre staActCentre= staActCentreService.selcetstaact(actualRoute.getId(),gosite);
        String date=staActCentre.getCarCometime();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, +1);//+1今天的时间加一天
        Date date1 = calendar.getTime();

        String getondate=sdfdate.format(date1);



        String getondates=getondate+" "+date;
        try {
//            String getondatelist=sdfdate.parse(getondate).getTime()+sdfst.parse(date).getTime();
            Tickettime = new Date(sdfs.parse(getondates).getTime() + 2 * 3600 * 1000);
            getontime=new Date(sdfs.parse(getondates).getTime() );
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Order order=new Order();
        Order orderactivity=orderService.selcetByUserid(userId,1);
        ActivityCentre activityCentre=activityCentreService.selectByActityState(1,userId,0);
        if(orderactivity==null&&activityCentre!=null){
            Activity activity=activityService.selectById(1);
            Date dateac=activity.getEndtime();
            Date n_date=new Date();
            if (dateac.getTime()>=n_date.getTime()){

                String money = actualRoute.getTicketPrice().getTicketPrice();
                float zongmoney=Float.valueOf(money);  //总共的金额  500
                BigDecimal price= activity.getPrice();  //优惠的金额  4
                float jian=price.floatValue();      //将优惠的金额转换为 float
                float jianprice=zongmoney-jian*100;  //用总的金额减去（优惠的金额乘100）得到实际支付的金额
    //            float jianprice=zongmoney-jian;
                String body = actualRoute.getLinename();
                order.setOpenid(null);//用户微信唯一标识符
                order.setTickettype("日票"); //现在都是日票
                order.setWeixinuserid(Integer.valueOf(userId));
                order.setState(0);  //状态未支付
                order.setPrice((int)jianprice);  //价格
                order.setLineid(actualRoute.getId());   //商品名称  我再这里写的是线路
                order.setWeixinnickname(null);  //用户微信昵称
                order.setNewdate(new Date());  //订单生成时间
                order.setGetontime(getontime); //上车时间
                order.setGoSite(gosite);  //上车站点
                order.setEndSite(endsite);//下车站点
                order.setTickettime(Tickettime);//车票有效时间
                order.setDisplaystate(0);
                order.setPaynum(payNum);
                orderService.insert(order);
                return order;
            }else {
                return order;
            }

        }else {
            return order;
        }
    }
    @Transactional
    public Order addRoOrder(Integer userId, ActualRoute actualRoute, Integer payNum ,Integer gosite,Integer endsite) {


        SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        SimpleDateFormat sdfdate = new SimpleDateFormat("yyyy-MM-dd");
        String startTime = sdfs.format(new Date());
        Date Tickettime = null;
        Date getontime = null;
        SimpleDateFormat sdfst = new SimpleDateFormat("HH:mm");
        StaActCentre staActCentre= staActCentreService.selcetstaact(actualRoute.getId(),gosite);
        String date=staActCentre.getCarCometime();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, +1);//+1今天的时间加一天
        Date date1 = calendar.getTime();

        String getondate=sdfdate.format(date1);



        String getondates=getondate+" "+date;
        try {
//            String getondatelist=sdfdate.parse(getondate).getTime()+sdfst.parse(date).getTime();
            Tickettime = new Date(sdfs.parse(getondates).getTime() + 2 * 3600 * 1000);  //乘车时间加上两个小时，车票过期

            getontime=new Date(sdfs.parse(getondates).getTime() );
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Order order=activityorder(userId, actualRoute, payNum,gosite,endsite);
        if (order.getId()==null) {

            String money = actualRoute.getTicketPrice().getTicketPrice();

            String body = actualRoute.getLinename();
            Order order1=new Order();
            order.setTickettype("日票"); //现在都是日票
            order.setWeixinuserid(Integer.valueOf(userId));
            order.setState(0);  //状态未支付
            order.setPrice(Integer.valueOf(money));  //价格
            order.setOpenid(null);//用户微信唯一标识符
            order.setLineid(actualRoute.getId());   //商品名称  我再这里写的是线路
            order.setWeixinnickname(null);  //用户微信昵称
            order.setNewdate(new Date());  //订单生成时间
            order.setGetontime(getontime); //上车时间
            order.setGoSite(gosite);  //上车站点
            order.setEndSite(endsite);//下车站点
            order.setTickettime(Tickettime);//车票有效时间
            order.setDisplaystate(0);
            order.setPaynum(payNum);
            orderService.insert(order);
        }
        Integer orderId=order.getId();
        TicketNum ticketNum = new TicketNum();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String gotontime = sdf.format(order.getGetontime());
        if (lock.tryLock()) {
            try {
                if (ticketNumService.getTicketnum(order.getLineid(), gotontime) == null) {
                   ActualRoute actualRoute1= actualRouteService.selectById(order.getLineid());
                    CarFile carFile=carFileService.selectById(actualRoute.getCarFileid());
                    String pedestal=carFile.getPedestal();
                    String digitalCode = arrlist();
                   ticketNum.setId(orderId);
                    ticketNum.setRemainingnum(Integer.valueOf(pedestal)-1);  //需要修改，如果座位不是45系统就崩了
                    ticketNum.setLineid(order.getLineid());
                    ticketNum.setTicketdate(gotontime);
                    ticketNum.setOrderid(orderId);
                    ticketNum.setDigitalcode(digitalCode);
//                    ticketNumService.insert(ticketNum);
                    ticketNum.insert();
                } else {
                    TicketNum ticketNum1 = ticketNumService.getTicketnum(order.getLineid(), gotontime);
                    if (ticketNum1.getRemainingnum() < 1 || ticketNum1.getRemainingnum() < payNum) {
                        throw new RuntimeException("余票不足!");
                    }
                    ticketNum1.setRemainingnum(ticketNum1.getRemainingnum() - 1);
                    ticketNumService.updateById(ticketNum1);

                }


            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        return order;
    }


    /**
     * @param request
     * @param userId
     * @return
     */
    @RequestMapping(value = "/pay")
    @ResponseBody
    public Map<String, Object> pay(HttpServletRequest request, @RequestParam("userId") Integer userId,
                                   @RequestParam("lineid") Integer lineid, @RequestParam("payNum") Integer payNum , @RequestParam("gosite") Integer gosite ,@RequestParam("endsite") Integer endsite,@RequestParam(required =false) Integer orderid ) {
        System.out.println("发起微信支付");
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        Map<String, Object> returnMap = new ConcurrentHashMap<String, Object>();
        ActualRoute act = actualRouteService.lineprice(lineid);
        String money = act.getTicketPrice().getTicketPrice();
//        Card card = cardService.selectById(cardId);
        /*
        支付之前加判断当前用户是否今天已经购票
         */
        Order order_weixin=orderdate(userId,lineid);
        if (order_weixin!=null){
            returnMap.put("order", "-2");
            returnMap.put("msg", "您好，您今天该条线路已购票");
            return returnMap;
        }
        if (act == null) {
            returnMap.put("act", "-1"); // 下单失败
            returnMap.put("msg", "没有找到路线");
            return returnMap;
        }

        Order order=orderService.selectById(orderid);
        if (order==null){
            order = this.addRoOrder(userId, act, payNum,gosite,endsite);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String gotontime = sdf.format(order.getGetontime());
//        Date Tickettime = null;
//        Date Gototimes = null;
        try {
           // Gototimes = new Date(sdf.parse(gotontime).getTime());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        WxPlaceOrder wxPlaceOrder = new WxPlaceOrder();
        wxPlaceOrder.setAppid(Configure.APP_ID);
        wxPlaceOrder.setBody(act.getLinename());
        wxPlaceOrder.setMch_id(Configure.PAY_ID);
        wxPlaceOrder.setNonce_str(Util.uuid());
        wxPlaceOrder.setNotify_url(Configure.NOTIFY_URL);
        Weixininfo user = weixinuserinfoService.selectById(userId);

        wxPlaceOrder.setOpenid(user.getOpenid());
        wxPlaceOrder.setOut_trade_no(OUT_TREADE_NUM_PREFIX + order.getId());
        wxPlaceOrder.setSpbill_create_ip("127.0.0.1");
        wxPlaceOrder.setTotal_fee(Integer.valueOf(String.valueOf(order.getPrice())));
        wxPlaceOrder.setTrade_type("JSAPI");
        wxPlaceOrder.setSign(Signature.getSign(wxPlaceOrder));
        XStream xStream = new XStream(new StaxDriver(new NoNameCoder()));
        xStream.alias("xml", WxPlaceOrder.class);
        String xml = xStream.toXML(wxPlaceOrder);
        String result = CommondUtil.httpsRequest(Configure.WX_PlACE_ORDER,
                "GET", xml);
        System.out.println("微信支付开始...xml:" + xml);
        System.out.println("微信支付开始...result:" + result);
        returnMap.put("code", "-1");// 下单失败
        if (!"".equals(result)) {
            try {
                map = XMLParser.getMapFromXML(result);
//                if (!"SUCCESS".equalsIgnoreCase((String) map.get("result_code"))) {
//                    resetTickNum(lineid, gotontime, payNum);
//                }
                if (map.containsKey("prepay_id")) {
                    // 统一下单接口成功
                    String prepay_id = (String) map.get("prepay_id");
                    // 签名 并返回前端
                    wxPlaceOrder = new WxPlaceOrder();
                    wxPlaceOrder.setAppid(Configure.APP_ID);
                    wxPlaceOrder.setNonce_str(Util.uuid());
                    wxPlaceOrder.setTimeStamp(System.currentTimeMillis() / 1000
                            + "");
                    wxPlaceOrder.setPrepay_id(prepay_id);

                    returnMap.put("nonce_str", wxPlaceOrder.getNonce_str());
                    returnMap.put("appid", Configure.APP_ID);
                    returnMap.put("timeStamp", wxPlaceOrder.getTimeStamp());
                    returnMap
                            .put("paySign", Signature.getSignPay(wxPlaceOrder));
                    returnMap.put("prepay_id", prepay_id);
                    returnMap.put("orderId", order.getId());
                    returnMap.put("code", "1");// 下单成功
                    return returnMap;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        resetTickNum(lineid, gotontime, payNum);   //当有这个字段没有调用微信的时候会加一
        System.out.println("微信支付结束");
        return returnMap;
    }

    private void resetTickNum(Integer lineid, String gotontime, Integer payNum) {
        //如果支付不成功
        tickLock.lock();
        try {
            TicketNum resTickNum = ticketNumService.getTicketnum(lineid, gotontime);
            resTickNum.setRemainingnum(resTickNum.getRemainingnum() + payNum);
            ticketNumService.updateById(resTickNum);
        } finally {
            tickLock.unlock();
        }
    }

    @RequestMapping(value = "/notify")
    @ResponseBody
    public void notity(HttpServletResponse response, HttpServletRequest request)
            throws Exception {
        System.out.println("微信支付回调开始...");

        Map<String, String> map = parseXml(request);
        WxPlaceOrder wxPlaceOrder = new WxPlaceOrder();
        // 当前订单的通知业务
        if ("SUCCESS".equals(map.get("return_code"))) {
            if ("SUCCESS".equals(map.get("result_code"))) {
                String out = map.get("out_trade_no");
                String paymentSeq = map.get("transaction_id");
                // 支付交易成功
                out = out.substring(out.lastIndexOf("-") + 1);
                Order order = orderService.selectById(out);
                TicketNum ticketNum = new TicketNum();

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                String gotontime = sdf.format(order.getGetontime());
                Date Tickettime = null;
                Date gotontimes=null;
                try {
                    Tickettime = new Date(sdf.parse(gotontime).getTime() + 2 * 3600 * 1000);
                    gotontimes = new Date(sdf.parse(gotontime).getTime());
//                order.setPayCode(paymentSeq);
                    order.setNewdate(new Date());//生成的订单时间
                    order.setTickettime(Tickettime);//车票有效时间
                    order.setGetontime(gotontimes);
//                order.setState(1);// 更新订单 为支付成功
                    order.setState(1);// 更新订单，支付完成
                    orderService.updateById(order);


                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            // 通知成功
            wxPlaceOrder.setReturn_code("SUCCESS");
            XStream xStream = new XStream(new StaxDriver(new NoNameCoder()));
            xStream.alias("xml", WxPlaceOrder.class);
            String returnXml = xStream.toXML(wxPlaceOrder);
            try {
                response.getWriter().write(returnXml);
            } catch (IOException e) {
                System.out.println("通知回调 微信服务器 异常");
            }
        }
        System.out.println("微信支付回调结束...");
    }

    public Map<String, String> parseXml(HttpServletRequest request)
            throws Exception, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(request.getInputStream());
        // 获取到document里面的全部结点
        NodeList allNodes = document.getFirstChild().getChildNodes();
        Node node;
        Map<String, String> map = new HashMap<String, String>();
        int i = 0;
        while (i < allNodes.getLength()) {
            node = allNodes.item(i);
            if (node instanceof Element) {
                map.put(node.getNodeName(), node.getTextContent());
            }
            i++;
        }
        return map;

    }

    @RequestMapping(value = "/cancelPay")
    @ResponseBody
    public Object cancelPay(@RequestParam("orderId") Integer orderId) {
        Order order = orderService.selectById(orderId);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        resetTickNum(order.getLineid(), sdf.format(order.getGetontime()), 1);
        return new SuccessTip();
    }



    public String arrlist() {
        List<String> array = new ArrayList<String>();
        Random rand = new Random();
        for (int i = 0; i < 4; i++) {
            int choice = rand.nextInt(3);
            switch (choice) {
                case 0:
                    int num = rand.nextInt(9);
                    array.add(String.valueOf(num));
                    break;
                case 1:
                    int num2 = rand.nextInt(25) + 65;
                    char low = (char) num2;
                    array.add(String.valueOf(low));
                    break;
                case 2:
                    int num3 = rand.nextInt(25) + 97;
                    char high = (char) num3;
                    array.add(String.valueOf(high));
                    break;
                default:
                    break;
            }
        }
        System.out.println("你得到的四位数字码：");
        StringBuffer str = new StringBuffer();
        for (String object : array) {
            System.out.print(object);
            str.append(object);
        }
        return str.toString();
    }


    @Transactional
    public Order orderdate(Integer userId,Integer lineid) {
        Map<String, Object> map = new ConcurrentHashMap<String, Object>();
        Map<String, Object> returnMap = new ConcurrentHashMap<String, Object>();
        Order orderdate=null;
        try{
            SimpleDateFormat newdate = new SimpleDateFormat("yyyy-MM-dd");
            String newdatestr = newdate.format(new Date());
            Date date=new Date();
            date=new Date(newdate.parse(newdatestr).getTime() );
            orderdate=orderService.selcetByNewdate(date,userId,1,lineid);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return  orderdate;
    }

}
